home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 43.5 KB | 1,927 lines | [TEXT/MPS ] |
- /* UMemory.cp */
- /* Copyright © 1985-1991 by Apple Computer, Inc. All rights reserved. */
-
- #ifndef __UMEMEORY__
- #include "UMemory.h"
- #endif
-
- #ifndef __STDIO__
- #include <StdIo.h>
- #endif
-
- #ifndef __UFAILURE__
- #include "UFailure.h"
- #endif
-
- #ifndef __MEMORY__
- #include "Memory.h"
- #endif
-
- #ifndef __TEXTEDIT__
- #include "Textedit.h"
- #endif
-
- #ifndef __OSUTILS__
- #include "OSUtils.h"
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include "UMacAppUtilities.h"
- #endif
-
- #ifndef __SYSEQU__
- #include "SysEqu.h"
- #endif
-
- #ifndef __TRAPS__
- #include "Traps.h"
- #endif
-
- #ifndef __DEVICES__
- #include "Devices.h"
- #endif
-
- #ifndef __ULOMEM__
- #include "ULoMem.h"
- #endif
-
- #ifndef __TOOLUTILS__
- #include "ToolUtils.h"
- #endif
-
- #ifndef __RESOURCES__
- #include "Resources.h"
- #endif
-
- #ifndef __PACKAGES__
- #include "Packages.h"
- #endif
-
- #ifndef __ERRORS__
- #include "Errors.h"
- #endif
-
- #ifndef __UDEBUG__
- #include "UDebug.h"
- #endif
-
- #ifndef __SEGLOAD__
- #include "SegLoad.h"
- #endif
-
- #ifndef __RTLIB__
- #include "RtLib.h"
- #endif
-
- #if qDebugMsg
- #ifndef __STDIO__
- #include <StdIO.h>
- #endif
- #endif
-
- #if !qDebugTheDebugger
- #pragma W+
- #pragma R-
- #pragma Init-
- #pragma OV-
- #endif
-
- // Globals to this module and externally available.
- Size gMaxLockedRsrc;
- #if qDebug
- Boolean gMemMgtBreak = FALSE;
- Boolean gRsrcReport = FALSE;
- Boolean gSegReport = FALSE;
- #endif
-
- HandleListHandle gSysMemList;
- HandleListHandle gApp1MemList;
- HandleListHandle gApp2MemList;
- short gCodeRefNum;
- HandleListHandle gCodeSegs;
- BoolListHandle gIsLoadedSeg;
- BoolListHandle gIsResidentSeg;
-
- // Static, globals to this module. Many of these are static by convention, but we don't
- // declare them as static because people may want to examine them.
-
- Boolean gUnloadAllSegs;
- ProcPtr gGZPurgeNotify;
- LongListHandle pSegSize;
- Handle pCodeReserve;
- Handle pMemReserve;
- Boolean pOKCodeReserve;
- Boolean pPermAllocation;
- Boolean pReserveExists;
-
- #if qDebug
- long pReserveShortfall;
- #endif
-
- Size pSzCodeReserve;
- Size pSzMemReserve;
- TrapPatch pSegLoadPatch;
- short pOldResFile;
- Boolean pLoadSegCalledFromOwnApp;
- short pMaxSegNum;
-
- // local private globals
- static Boolean pDuringGrowZone;
- static SegLoadHdlrPtr oldPreLoadHandler;
- static SegLoadHdlrPtr oldPostLoadHandler;
-
- // Function prototypes for some routines in this module.
-
- pascal long GrowZoneProc(Size needed);
-
- // Function prototypes for the routines in UMemory.a
-
- pascal void ALoadMacAppSeg(void);
-
- /* LoadSeg is Patched to call ALoadMacAppSeg, which in turn calls
- LoadMacAppSegment. ALoadMacAppSeg can only be referenced as a
- procedure pointer, because no args are declared */
-
- // Other function prototypes that are externally defined.
-
- typedef pascal void( *DoToFrameType)(long,
- long,
- long,
- long,
- void *);
-
- pascal void EachFrameDo(long calleeFrame,
- long ppc,
- DoToFrameType DoToFrame,
- void *scopeLink);
-
- pascal void CallNotify(Handle h,
- ProcPtr routine) = {
- 0x205F, 0x4E90};// MOVE.L (A7)+,A0; JSR (A0)
-
- pascal short CallHandler(RTState* state,
- SegLoadHdlrPtr routine) = {
- 0x205F, 0x4E90};// MOVE.L (A7)+,A0; JSR (A0)
-
- //--------------------------------------------------------------------------------------------------
-
- // These "MAFoo" functions are primarily for THINK™ Pascal compatibility (but useful in the larger
- // problem of multiple open resource maps in general); when running under the THINK™ environment,
- // CODE resources are not found in the same resource file as other application resources, so a
- // UseResFile call needs to be made to bring the project resource file into the search path.
- // "gCodeRefNum" is set up at initialization time.
- // !!! A much more general solution to "the resource problem" appears to be warranted.
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGet1Resource(ResType rType,
- short rID)
- {
- short oldResFile;
- Handle resource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resource = Get1Resource(rType, rID);
- MAUseResFile(oldResFile);
-
- return resource;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGet1NamedResource(ResType rType,
- const Str255 &name)
- {
- short oldResFile;
- Handle namedResource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- namedResource = Get1NamedResource(rType, name);
- MAUseResFile(oldResFile);
-
- return namedResource;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGet1IndResource(ResType rType,
- short index)
- {
- short oldResFile;
- Handle indResource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- indResource = Get1IndResource(rType, index);
- MAUseResFile(oldResFile);
-
- return indResource;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal short MACount1Resources(ResType rType)
- {
- short oldResFile;
- short resourceCnt;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resourceCnt = Count1Resources(rType);
- MAUseResFile(oldResFile);
-
- return resourceCnt;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGetResource(ResType rType,
- short rID)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetResource(rType, rID);
- MAUseResFile(oldResFile);
-
- return HomeResFile(h) != gCodeRefNum ? NULL : h;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGetNamedResource(ResType rType,
- const Str255 &name)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetNamedResource(rType, name);
- MAUseResFile(oldResFile);
-
- return HomeResFile(h) != gCodeRefNum ? NULL : h;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle MAGetIndResource(ResType rType,
- short index)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetIndResource(rType, index);
- MAUseResFile(oldResFile);
-
- return HomeResFile(h) != gCodeRefNum ? NULL : h;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal short MACountResources(ResType rType)
- {
- short oldResFile;
- short resourceCnt;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resourceCnt = CountResources(rType);
- MAUseResFile(oldResFile);
-
- return resourceCnt;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle GetSegResource(short segNum)
- {
- return MAGet1Resource(kCode, segNum);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal void AddAllRsrc(ResType rType,
- HandleListHandle toList)
- {
- Boolean oldResLoad;
- short i,
- nResources,
- theID;
- Handle h;
- ResType theType;
- Str255 theName;
-
- oldResLoad = GetResLoad();
- SetResLoad(FALSE);
-
- nResources = CountResources(rType);
- for (i = 1; i <= nResources; ++i)
- {
- h = GetIndResource(rType, i);
- GetResInfo(h, theID, theType, theName);
-
- /* If there is a ROM resource for this type and ID, don't put it
- on the list. */
-
- UseROMMap(FALSE);
- h = GetResource(rType, theID);
- UseROMMap(FALSE);
- if (HomeResFile(h) != 1)
- AddHandle(h, toList);
- }
-
- SetResLoad(oldResLoad);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal void AddHandle(Handle h,
- HandleListHandle toList)
- {
- long offset;
-
- offset = Munger((Handle)toList, 0, NULL, 0, (Ptr) & h, 4);
- FailMemError();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal long AddSegSizes(Handle segRsrc)
- {
- SignedByte savedState;
- SignedBytePtr p;
- Boolean oldResLoad;
- register long total;
- Handle seg;
- short i;
- Str255 s;
-
- savedState = LockHandleHigh(segRsrc);
-
- oldResLoad = GetResLoad();
- SetResLoad(FALSE);
-
- p = (SignedBytePtr) * segRsrc;
- i = *((IntegerPtr)p);
- p += 2;
-
- total = 0;
-
- for (; i > 0; i--, p += *p + 1)
- {
- BlockMove((Ptr)p, (Ptr) & s, *p + 1);
- seg = MAGet1NamedResource(kCode, s);
- if (seg)
- total += SizeResource(seg) + 8;
- }
-
- SetResLoad(oldResLoad);
- HSetState(segRsrc, savedState);
-
- return total;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- Boolean IsHandleEligible(Handle h)
- {
- if (h == NULL)
- return FALSE; // Thanks Pillar!
- else if (IsHandlePurged(h))
- return FALSE;
- else
- return (h != GetGZMoveHnd()) && (h != GetGZRootHnd());
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- void BuildCodeReserve(Size allocLim,
- Boolean fromGZ)
- {
- static const short initVal = 0xF7;
-
- Size needed, avail;
- Handle canPurge = 0;
- #if qDebug
- Size theSize;
- #endif
-
- pOKCodeReserve = TRUE; // default value
-
- #if qDebug
- pReserveShortfall = 0;
-
- if (!pPermAllocation)
- ProgramBreak("BuildCodeReserve called with pPermAllocation = FALSE");
- #endif
-
- if (!pReserveExists)
- {
- pReserveExists = TRUE; // default value
-
- // free the current code reserve
- if (IsHandleEligible(pCodeReserve))
- EmptyHandle(pCodeReserve);
-
- // compute amt actually needed
- needed = Min(pSzCodeReserve - TotalTempSize(FALSE, canPurge) - 8, allocLim);
-
- if (needed > 0)
- {
- // make as much memory available as possible
- if (IsHandleEligible(pMemReserve))
- EmptyHandle(pMemReserve);
-
- if (fromGZ) // Never purge or compact from GrowZone
- avail = allocLim;
- else
- {
- PurgeMem(needed);
- avail = CompactMem(needed);
- }
-
- if (avail < needed) // could not get the whole reserve
- {
- #if qDebug
- pReserveShortfall = needed - avail;
- #endif
-
- pOKCodeReserve = FALSE;
- pReserveExists = FALSE;
-
- needed = avail; // get the most we can
- }
-
- if (!fromGZ && (IsHandlePurged(pCodeReserve) || IsHandleEligible(pCodeReserve)))
- ReallocHandle(pCodeReserve, needed);
- #if qDebug
- theSize = GetHandleSize(pCodeReserve);
- #pragma Push
- #pragma R-
- if (theSize != 0)
- BlockSet(*pCodeReserve, theSize, initVal);
- #pragma Pop
- #endif
-
- if (!IsHandlePurged(pCodeReserve))
- {
- /* Large handles are almost as bad as nonrelocatable blocks.
- Try to get this guy out of the way, just in case.*/
-
- if (!fromGZ)
- MoveHHi(pCodeReserve);
- }
- }
- }
- }
- /*$Pop*/
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- pascal void BuildAllReserves()
-
- {
- static const short initVal = 0xF7;
-
- Boolean oldPerm;
- #if qDebug
- Size theSize;
- #endif
-
- /* set the permanent flag to ensure that the code reserve is
- actually allocated and not given up to the low space reserve */
-
- oldPerm = pPermAllocation;
- pPermAllocation = TRUE;
-
- BuildCodeReserve(kGZMaxAlloc, FALSE); // make sure code reserve is OK
-
- // reallocate the low space handle, if necessary
-
- if (IsHandlePurged(pMemReserve))
- {
- ReallocHandle(pMemReserve, pSzMemReserve);
- #if qDebug
- theSize = GetHandleSize(pMemReserve);
- #pragma Push
- #pragma R-
- if (theSize != 0)
- BlockSet(*pMemReserve, theSize, initVal);
- #pragma Pop
- #endif
-
- }
-
- pPermAllocation = oldPerm; // reset the permanent flag
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Boolean CheckReserve()
- {
- BuildAllReserves();
- return pOKCodeReserve;
- }
-
- //--------------------------------------------------------------------------------------------------
- #if qDebug
- #pragma segment MAMemoryRes
-
- pascal void CheckRsrcUsage()
- {
- long sz;
- Handle h;
- Str255 s;
-
- sz = TotalTempSize(TRUE, h);
- if (sz > gMaxLockedRsrc)
- {
- gMaxLockedRsrc = sz;
- if (gRsrcReport)
- {
- NumToString(gMaxLockedRsrc, s);
- s = " = New maximum resources usage: " + s + " =";
- ProgramReport(s, gMemMgtBreak);
- }
- }
- }
- #endif
-
- //--------------------------------------------------------------------------------------------------
- #if qDebug
- #pragma segment MADebug
-
- pascal void DoChangeReserve(Boolean alter,
- Size &codeReserve,
- Size &codeShort,
- Size &lowSpaceReserve,
- Boolean &gotCode,
- Boolean &gotLowSpace)
- {
- long x;
- Str255 s;
- char cS[10];
-
- if (alter)
- {
- fprintf(stderr, "code reserve size = %ld ", pSzCodeReserve);
- if (pOKCodeReserve)
- fprintf(stderr, " (OK)\n");
- else
- fprintf(stderr, " (gone)\n");
-
- fprintf(stderr, "low space reserve size = %ld ", pSzMemReserve);
- if (!IsHandlePurged(pMemReserve))
- fprintf(stderr, " (OK)\n");
- else
- fprintf(stderr, " (gone)\n");
-
- fprintf(stderr, "\n");
-
- fprintf(stderr, "New code reserve (-1 == no change): ");
- fscanf(stdin, "%ld", &x);
- if (x >= 0)
- codeReserve = x;
- else
- codeReserve = pSzCodeReserve;
-
- fprintf(stderr, "New low space reserve (-1 == no change): ");
- fscanf(stdin, "%ld", &x);
- if (x >= 0)
- lowSpaceReserve = x;
- else
- lowSpaceReserve = pSzMemReserve;
-
- fprintf(stderr, "Reset max resource usage (Y or N) [N]? ");
- fscanf(stdin, "%s", cS);
- s = cS;
- if (!s.IsEmpty())
- {
- if ((s[1] == 'y') || (s[1] == 'Y'))
- gMaxLockedRsrc = 0;
- }
-
- fprintf(stderr, "\n");
-
- SetReserveSize(codeReserve, lowSpaceReserve);
- }
- else
- BuildAllReserves();
-
- codeReserve = pSzCodeReserve;
- codeShort = pReserveShortfall;
- lowSpaceReserve = pSzMemReserve;
- gotCode = pOKCodeReserve;
- gotLowSpace =!IsHandlePurged(pMemReserve);
- }
- #endif
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- /* Called from InitUMemory so that InitUMemory can be in the main segment
- and this code can be in another (unloadable) segment. */
-
- pascal void DoInitUMemory(Size &sizeTempReserve,
- Size &sizeLowSpaceReserve)
- {
- struct Mem
- {
- long codeVal, lowSpaceVal, stackVal;
- };
-
-
- typedef Mem *MemPtr,
- **MemHandle;
-
- short i,
- rsrcCnt;
- Boolean oldResLoad;
- Handle seg, h;
- long stackTot;
- short rsrcID;
- ResType rsrcType;
- Str255 rsrcName;
- short lastRsrc;
- short mainSegment, utilitySegment;
-
- // Initialize memory management globals
-
- pPermAllocation = FALSE;
- pMemReserve = NewHandle(0);
- FailNIL(pMemReserve);
-
- pSzMemReserve = 0;
- pCodeReserve = NewHandle(0);
- FailNIL(pCodeReserve);
-
- pSzCodeReserve = 0;
- gGZPurgeNotify = NULL;
- pOKCodeReserve = TRUE;
- pReserveExists = FALSE;
-
- gUnloadAllSegs = TRUE;
-
- gCodeRefNum = HomeResFile(GetResource(kCode, 1));/* Get homeresfile of "Main". It better be
- there!!*/
- pMaxSegNum = 0;
-
- //###########################################
- // No resource loading
-
- oldResLoad = GetResLoad();
- SetResLoad(FALSE);
-
- // Figure the highest segment number
- lastRsrc = MACount1Resources(kCode);
-
- /* some development systems may not have contiguous numbering of CODE segments.
- try to be polite about handling it */
-
- for (i = 1; i <= lastRsrc; ++i)
- {
- seg = MAGet1IndResource(kCode, i);
-
- /* we only have an index… find the real resource ID and keep track
- of the highest one */
-
- if (seg)
- {
- GetResInfo(seg, rsrcID, rsrcType, rsrcName);
- pMaxSegNum = (short)Max(rsrcID, pMaxSegNum);
- }
- }
-
- SetResLoad(oldResLoad); // in case of failure
-
- // Allocate the master segment lists.
- gCodeSegs = (HandleListHandle)NewHandle(pMaxSegNum * sizeof(Handle));
- FailNIL(gCodeSegs);
-
- gIsResidentSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
- FailNIL(gIsResidentSeg);
-
- gIsLoadedSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
- FailNIL(gIsLoadedSeg);
-
- /* (NOTE: assumes application doesn't change the CODE segment size at runtime
- (a very safe assumption)). Used in GetSegFromPC. */
-
- pSegSize = (LongListHandle)NewHandle(pMaxSegNum * sizeof(long));
- FailNIL(pSegSize);
-
- oldResLoad = GetResLoad(); // OK, suppress segment loading again
- SetResLoad(FALSE); /* !!! Need an MAResLoad that returns old
- state */
-
- // Segments and their sizes and actual loaded state (helps catch preloads)
-
- for (i = 0; i < pMaxSegNum; ++i)
- {
- (*gIsResidentSeg)[i] = FALSE;
- seg = GetSegResource(i + 1);
- (*gCodeSegs)[i] = seg;
- if (seg) // seg is non-nil if the segment number
- (*pSegSize)[i] = SizeResource(seg);
- else
- (*pSegSize)[i] = 0;
-
- (*gIsLoadedSeg)[i] = TRUE; // Assume all segments are loaded
- }
-
- SetResLoad(oldResLoad);
- //###########################################
-
- mainSegment = GetSegNumber((ProcPtr) & InitUMemory);// Main is always resident
- (*gIsResidentSeg)[mainSegment - 1] = TRUE;
-
- utilitySegment = GetSegNumber((ProcPtr) & UnloadAllSegments);// Utilities are always resident
- (*gIsResidentSeg)[utilitySegment - 1] = TRUE;
-
- if (qModelFarCode)
- (*gIsResidentSeg)[pMaxSegNum - 1] = TRUE;// 32-bit bootstrap is always last
- // _AND_ resident
-
- // init the gSysMemList
-
- gSysMemList = (HandleListHandle)NewHandle(0);
- FailNIL(gSysMemList);
-
- AddAllRsrc('LDEF', gSysMemList);
- AddAllRsrc('CDEF', gSysMemList);
- AddAllRsrc('MDEF', gSysMemList);
- AddAllRsrc('WDEF', gSysMemList);
- AddAllRsrc('PACK', gSysMemList);
-
- // Compute memory slop needed
-
- sizeTempReserve = 0;
- sizeLowSpaceReserve = 0;
- stackTot = 0;
-
- rsrcCnt = CountResources('seg!');
- for (i = 1; i <= rsrcCnt; ++i)
- {
- h = GetIndResource('seg!', i);
- sizeTempReserve += AddSegSizes(h);
- ReleaseResource(h);
- }
-
- rsrcCnt = CountResources('mem!');
- for (i = 1; i <= rsrcCnt; ++i)
- {
- h = GetIndResource('mem!', i);
- {
- const Mem &memH = **((MemHandle)h);
-
- sizeTempReserve += memH.codeVal;
- sizeLowSpaceReserve += memH.lowSpaceVal;
- stackTot += memH.stackVal;
- }
- ReleaseResource(h);
- }
-
- SetStackSpace(stackTot);
-
- MaxApplZone();
-
- gApp1MemList = NULL;
- gApp2MemList = NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void FailNoReserve()
- {
- if (!CheckReserve())
- Failure(memFullErr, 0);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void FailSpaceIsLow()
- {
- #if qDebug
- MAName s;
-
- if (gAskFailure && CanReadLn())
- {
- GetCallersMethodName(s);
- if (ReadYesNo("FailSpaceIsLow called by " + s + ". Return true(Y or N) [N]? "))
- Failure(memFullErr, 0);
- }
- #endif
-
- if (MemSpaceIsLow())
- Failure(memFullErr, 0);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- #pragma segment MAMemoryRes
-
- pascal void GetReserveSize(Size &szCodeReserve,
- Size &szMemReserve)
- {
- szCodeReserve = pSzCodeReserve;
- szMemReserve = pSzMemReserve;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
- #pragma segment MAMemoryRes
- // Shouldn't be unloaded
-
- pascal short GetSegFromPC(long ppc)
- {
- long pc,
- segStart;
- short i;
- Handle seg;
-
- pc = *((LongIntPtr)ppc);
-
- /* Since GetSegFromPC may be called before gCodeSegs is set up, we have to test if gCodeSegs == NULL
- before using it. */
-
- if (gCodeSegs)
- for (i = 0; i < pMaxSegNum; ++i)
- {
- seg = (*gCodeSegs)[i]; // get segment handle
- if ((seg) &&!IsHandlePurged(seg)) // it's in memory
- {
- segStart = StripLong(*seg); // get segment start
- if ((pc >= segStart) && (pc < segStart + (*pSegSize)[i]))
- return i + 1;
- }
- }
-
- return 0; // default return
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
-
- #pragma segment MAMemoryRes
- /* must be in Main segment because we call
- this in order to make the resident segment resident */
-
- pascal short GetSegNumber(ProcPtr aProc)
- // Gets seg number from a Jump table address
- {
- static const short kLoaded = 0x4EF9; // if loaded then a JMP instruction
- static const short kUnLoaded = 0x3F3C; // if unloaded then a LoadSeg trap
-
- if (*((IntegerPtr)aProc) == kLoaded) // loaded segment
- return *((IntegerPtr)((long)aProc - 2));
- else if (*((IntegerPtr)aProc) == kUnLoaded) // unloaded segment
- return *((IntegerPtr)((long)aProc + 2));
- else /* routine that computed &proc was in same
- segment as the proc */
- {
- #if qDebug
- ProgramBreak("GetSegNumber was not passed an jump table address");
- #endif
-
- return 0;
- }
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- pascal Size GetSegSize(short segNum)
- {
- return (*pSegSize)[segNum - 1];
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- pascal long GrowZoneProc(Size)
- {
- long result,
- reserveSize,
- OldA5;
- Handle canPurge;
- Size codeSize;
-
- OldA5 = SetCurrentA5(); // Can be called from other worlds
-
- result = 0; // default is to fail
-
- if (!pDuringGrowZone) // prevent re-entrancy
- {
- pDuringGrowZone = TRUE;
-
- // on a temp alloc, free all code slack immediately
-
- if (!pPermAllocation && IsHandleEligible(pCodeReserve))
- {
- EmptyHandle(pCodeReserve);
- pReserveExists = FALSE;
- result = 1;
- }
-
- if (result == 0) /* try harder: see if we can purge a code
- segment or reduce the code reserve handle
- */
- {
- // compute size of resources currently in memory
-
- codeSize = TotalTempSize(FALSE, canPurge);
-
- // see if the code reserve handle is too large
-
- if (IsHandleEligible(pCodeReserve))
- /* we have a code reserve handle; this implies permanent allocation,
- otherwise the handle would have been emptied above */
- {
- reserveSize = GetHandleSize(pCodeReserve);
-
- /* the following test is an optimization to avoid calling
- BuildCodeReserve if there is no hope of reducing
- the code reserve handle */
-
- if (codeSize + reserveSize + 8 > pSzCodeReserve)
- {
- // reserve is too big
- pReserveExists = FALSE;
- // this should lower the code reserve
- BuildCodeReserve(reserveSize, TRUE);
-
- // see if we succeeded in freeing some memory
- if (IsHandlePurged(pCodeReserve))
- result = 1;
- else if (GetHandleSize(pCodeReserve) < reserveSize)
- result = 1;
- }
- }
-
- if ((result == 0) && (canPurge) && (!pPermAllocation || IsHandlePurged(pCodeReserve)))/* got something; only purge it if this is
- temporary || we know there is too much
- code in memory already */
- {
- if (gGZPurgeNotify)
- CallNotify(canPurge, gGZPurgeNotify);
-
- reserveSize = GetHandleSize(canPurge);
- HPurge(canPurge);
- EmptyHandle(canPurge);
- pReserveExists = FALSE;
-
- if (pPermAllocation) // don't free too much however
- BuildCodeReserve(reserveSize, TRUE);
-
- result = 1;
- }
- }
-
- if ((result == 0) && IsHandleEligible(pMemReserve))/* last ditch attempt-free emergency
- reserve*/
- {
- EmptyHandle(pMemReserve);
- result = 1;
- }
-
- pDuringGrowZone = FALSE;
- }
-
- OldA5 = SetA5(OldA5);
-
- return result;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- // Must be in same segment as grow zone proc
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- void InstallGrowZoneProc()
- /* Once called the grow zone proc's segment CAN!be moved since we're passing a NON-JT address
- to SetGrowZone (so we can be called from "other worlds" */
- {
- THz aZone;
-
- pDuringGrowZone = FALSE;
- aZone = ApplicZone();
- aZone->flags |= 0x0400;
-
- /* set the Memory Manager bit that says to always call the
- Grow Zone proc, even in "non-critical" situations */
-
- SetGrowZone(&GrowZoneProc);
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- #pragma segment MAMemoryRes
-
- pascal short PreloadHandler(RTState* state)
-
- {
- LoadMacAppSegment(state->fSegNo);
-
- if (oldPreLoadHandler)
- return CallHandler(state, oldPreLoadHandler);
- else
- return 0;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
- #pragma Z+
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal void PostLoadMacAppSegment()
- {
- long A5RegisterOnEntry = SetCurrentA5(); // ***** Called from trap patches *****
- // test if called from our application… if so, don't do patch behaviour. Thank you McSink!
- if (GetA5() == A5RegisterOnEntry && pLoadSegCalledFromOwnApp)
- MAUseResFile(pOldResFile); // Called back from our glue. Restores current res file pointer.
- SetA5(A5RegisterOnEntry);
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- #pragma segment MAMemoryRes
-
- pascal short PostloadHandler(RTState* state)
-
- {
- PostLoadMacAppSegment();
- if (oldPostLoadHandler)
- return CallHandler(state, oldPostLoadHandler);
- else
- return 0;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment Main
- // Must be in main segment and called from main segment
-
- pascal void InitUMemory()
- {
-
- Size codeRes, lowSpaceRes = 0;
- Handle miniInitSeg;
-
- /* Get these segments out of the way so that when DoInitUMemory gets called and the next
- block of master pointers gets allocated they won't constipate the heap */
-
- miniInitSeg = GetResource(kCode, GetSegNumber((ProcPtr) & DoInitUMemory));
- if (miniInitSeg)
- {
- UnloadSeg(&DoInitUMemory);
- LockHandleHigh(miniInitSeg);
- }
-
- DoInitUMemory(codeRes, lowSpaceRes);
-
- UnloadAllSegments(); /* get init segment(s) out of middle of heap,
- so SetReserveSize has maximum space to
- work with */
-
- if (miniInitSeg) /* Yes, this would eventually get purged if
- the space was needed badly enough, but
- that happens very late in the game and can
- confound the unwary */
- EmptyHandle(miniInitSeg);
-
- InstallGrowZoneProc();
-
- SetReserveSize(codeRes, lowSpaceRes);
- if (!pOKCodeReserve) /* couldn't get code reserve. Can't continue */
- Failure(memFullErr, 0);
- else
- {
- // Set up the LoadSeg patch
-
- if (qModelFarCode) // Use the cool new RTLib so graciously
- // provided by Landon and Sandra
- {
- RTPB anRTPB;
-
- // Install the preload handler
- anRTPB.fOperation = kRTSetPreLoad;
- anRTPB.fUserHdlr = PreloadHandler;
- if (Runtime(&anRTPB) != noErr)
- Failure(minErr, 0); // !!! need to assign a code someday
- oldPreLoadHandler = anRTPB.fOldUserHdlr;
-
- // Install the postload handler
- anRTPB.fOperation = kRTSetPostLoad;
- anRTPB.fUserHdlr = PostloadHandler;
- if (Runtime(&anRTPB) != noErr)
- Failure(minErr, 0); //!!! need to assign a code someday
- oldPostLoadHandler = anRTPB.fOldUserHdlr;
-
- pSegLoadPatch.OldTrapAddr = NGetTrapAddress(_LoadSeg, GetTrapType(_LoadSeg));
- }
- else
- FailOSErr(PatchTrap(pSegLoadPatch, _LoadSeg, (Ptr) & ALoadMacAppSeg));
- }
- }
-
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal long LoadMacAppSegment(short segNum)
- {
- #if qDebug
- short id;
- ResType kind;
- Str255 segName;
- MAName s;
- Handle seg;
- #endif
-
- long A5RegisterOnEntry;
- long loadMacAppSegment;
-
- A5RegisterOnEntry = SetCurrentA5(); // ***** Called from trap patches *****
-
- loadMacAppSegment = pSegLoadPatch.oldTrapAddr;// Where to go next
-
- if (GetA5() != A5RegisterOnEntry)
- {
- // not called from our application… don't do patch behaviour. Thank you McSink!
- pLoadSegCalledFromOwnApp = FALSE;
- SetA5(A5RegisterOnEntry);
- }
- else
- {
- pLoadSegCalledFromOwnApp = TRUE;
- pOldResFile = MAUseResFile(gCodeRefNum);/* Must set a global because we return from
- this function and then forward to the
- actual segment loader which should also be
- pointing to the _now_ correct resfile.
- When we get called back again in
- PostLoadMacAppSegment we will restore the
- old resFile as the current resFile. Sorry
- about the global. */
-
- #if qDebug
- if (!GetResLoad())
- {
- SetResLoad(TRUE);
- ProgramBreak("Whoops… LoadSeg called with resload set false");
- Failure(minErr, 0); /*??? Assign an error code someday or
- setresload to true ???*/
- }
-
- #endif
-
- if (!PreloadSegmentResource(segNum))
- {
- #if qDebug
- GetCallersMethodName(s);
- SetResLoad(FALSE);
- seg = MAGet1Resource(kCode, segNum);
-
- GetResInfo(seg, id, kind, segName);
- SetResLoad(TRUE);
- //###SRF ProgramBreak("In " + s + form(" couldn''t load segment: %d", segNum) + segName);
- #endif
-
- Failure(memFullErr, 0);
- }
-
- (*gIsLoadedSeg)[segNum - 1] = TRUE;
-
- #if qDebug
- if (gSegReport)
- {
- // Cause the debugger to break at the start of the next routine.
- gReportNext = TRUE;
- GetResInfo((*gCodeSegs)[segNum - 1], id, kind, segName);
- //###SRF gReportInfo = form(" *** Segment Loaded: %d ", segNum) + segName;
- gSingleStep = gMemMgtBreak;
- }
- #endif
-
- }
-
- return loadMacAppSegment;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- // Must be in Main segment
-
- pascal void LoadResidentSegments()
- {
- short offset,
- segNumber,
- rsrcCnt;
- Handle nameList, seg;
- SignedBytePtr p;
- Str255 name;
- ResType theType;
- char savedState;
-
- rsrcCnt = CountResources('res!');
- for (short resIndex = 1; resIndex <= rsrcCnt; ++resIndex)
- {
- nameList = GetIndResource('res!', resIndex);
- savedState = HGetState(nameList);
- HLock(nameList); // lock it down for BlockMove
-
- offset = 2;
- for (short i = 1; i <= *((IntegerPtr) * nameList); ++i)
- {
- p = (SignedBytePtr)(*nameList + offset);
- BlockMove((Ptr)p, (Ptr) & name, *p + 1);
- offset += name.Length() + 1;
-
- seg = MAGet1NamedResource(kCode, name);
-
- if (seg)
- {
- GetResInfo(seg, segNumber, theType, name);
- SetResidentSegment(segNumber, TRUE);
- }
- }
-
- HSetState(nameList, savedState);
- ReleaseResource(nameList);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Boolean MemSpaceIsLow()
- {
- BuildAllReserves();
- return IsHandlePurged(pMemReserve);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Handle NewPermHandle(Size logicalSize)
- {
- static const short initVal = 0xF3; // odd at all byte boundaries
-
- Boolean priorPerm;
- Handle aHandle;
-
- priorPerm = PermAllocation(TRUE);
- aHandle = NewHandle(logicalSize);
- pPermAllocation = priorPerm;
- FailNIL(aHandle);
- #pragma Push
- #pragma R-
- if (qDebug)
- BlockSet(*aHandle, logicalSize, initVal);
- #pragma Pop
- return aHandle;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal Ptr NewPermPtr(Size logicalSize)
- {
- static const short initVal = 0xF3; // odd at all byte boundaries
-
- Boolean priorPerm;
- Ptr aPtr;
-
-
- priorPerm = PermAllocation(TRUE);
- aPtr = NewPtr(logicalSize);
- pPermAllocation = priorPerm;
- FailNIL(aPtr);
- #pragma Push
- #pragma R-
- if (qDebug)
- BlockSet(aPtr, logicalSize, initVal);
- #pragma Pop
- return aPtr;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- #pragma segment MAMemoryRes
-
- pascal Boolean PermAllocation(Boolean permanent)
- {
- Boolean permAllocation = pPermAllocation;
-
- if (permanent != pPermAllocation)
- {
- pPermAllocation = permanent;
- if (permanent)
- BuildCodeReserve(kGZMaxAlloc, FALSE);
- }
-
- return permAllocation;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
- // must be in Main segment
- #pragma segment MAMemoryRes
-
- class CWithCodeResFileDo
- {
- short &fSegNum;
- Handle &fSeg;
- public:
- CWithCodeResFileDo(short &segNum,
- Handle &seg)
- :
- fSegNum(segNum),
- fSeg(seg)
- {
- }
-
- pascal void DoGetSegHandle();
- };
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal void CWithCodeResFileDo::DoGetSegHandle()
- {
- fSeg = Get1Resource(kCode, fSegNum);
- }
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal Boolean PreloadSegmentResource(short segNum)
- {
- Handle seg;
- CWithCodeResFileDo scopeLink(segNum, seg);
-
- if (qDebug && pPermAllocation)
- {
- fprintf(stderr, "segment # = %d", segNum);
- ProgramBreak("Trying to load a segment with PermAllocation == true.");
- }
-
- WithCodeResFileDo((DoWithResFileType) & CWithCodeResFileDo::DoGetSegHandle, &scopeLink);
-
- if (!seg)
- return FALSE;
- else
- {
- if (!IsHandleLocked(seg)) // not yet locked
- LockHandleHigh(seg);
- return TRUE;
- }
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void RemHandle(Handle h,
- HandleListHandle toList)
- {
- long p,
- maxP,
- offset;
-
- p = (long) * toList; // Address of first element
- maxP = p + GetHandleSize((Handle)toList); // Address past last element
-
- // Skip elements until item is found
- while ((p < maxP) && *((LongIntPtr)p) != (long)h)
- p += sizeof(Handle);
-
- if (p < maxP) // Item was found
- {
- offset = Munger((Handle)toList, p - (long) * toList, NULL, sizeof(Handle), (Ptr) & h, 0);
- FailMemError();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- typedef Handle *HandlePtr;
-
- void ScanList(HandleListHandle list,
- DoToHandlesType DoToHandle,
- void *scopeLink)
- {
- HandlePtr p = (HandlePtr) * list;
-
- for (short i = (short)(GetHandleSize((Handle)list) / sizeof(Handle)); i > 0; --i, ++p)
- DoToHandle(*p, scopeLink);
- }
-
-
- pascal void ScanHandles(DoToHandlesType DoToHandle,
- void *scopeLink)
- {
- ScanList(gCodeSegs, DoToHandle, scopeLink);
- if (gApp1MemList)
- ScanList(gApp1MemList, DoToHandle, scopeLink);
- ScanList(gSysMemList, DoToHandle, scopeLink);
- if (gApp2MemList)
- ScanList(gApp2MemList, DoToHandle, scopeLink);
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void SetPermHandleSize(Handle h,
- Size newSize)
- {
- static const short initVal = 0xF3;
-
- Boolean priorPerm;
- #if qDebug
- Size oldSize;
- #endif
-
- priorPerm = PermAllocation(TRUE);
- #if qDebug
- oldSize = GetHandleSize(h);
- #endif
-
- SetHandleSize(h, newSize);
- pPermAllocation = priorPerm; /* Since we are in the memory unit we can
- break the encapsulation of the
- PermAllocation Call to just set the
- pPermAllocation flag back directly. This
- lets us be assured that no operations have
- occurred that would invalidate the MemErr
- flag… thus the following call will give a
- true result*/
- FailMemError();
- #if qDebug
- #pragma Push
- #pragma R-
- if (oldSize < newSize)
- BlockSet((Ptr) * h + oldSize, newSize - oldSize, initVal);
- #pragma Pop
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void SetPermPtrSize(Ptr p,
- Size newSize)
- {
- static const short initVal = 0xF5;
-
- Boolean priorPerm;
- #if qDebug
- Size oldSize;
- #endif
-
- priorPerm = PermAllocation(TRUE);
- #if qDebug
- oldSize = GetPtrSize(p);
- #endif
-
- SetPtrSize(p, newSize);
- pPermAllocation = priorPerm; /* Since we are in the memory unit we can
- break the encapsulation of the
- PermAllocation Call to just set the
- pPermAllocation flag back directly. This
- lets us be assured that no operations have
- occurred that would invalidate the MemErr
- flag… thus the following call will give a
- true result*/
- FailMemError();
- #if qDebug
- #pragma Push
- #pragma R-
- if (oldSize < newSize)
- BlockSet((Ptr)p + oldSize, newSize - oldSize, initVal);
- #pragma Pop
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- pascal void SetReserveSize(Size forCode,
- Size forOther)
- {
- pSzCodeReserve = forCode;
- pSzMemReserve = forOther;
-
- // Since the numbers have changed, make sure we start from scratch.
- pReserveExists = FALSE;
- EmptyHandle(pMemReserve);
-
- BuildAllReserves();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal void SetResidentSegment(short segNum,
- Boolean makeResident)
- {
- #if qDebug
- short id;
- ResType kind;
- Str255 segName;
- MAName s;
- Handle seg;
- #endif
-
- if (makeResident)
- {
- (*gIsResidentSeg)[segNum - 1] = TRUE;
- if (!PreloadSegment(segNum))
- {
- #if qDebug
- GetCallersMethodName(s);
- SetResLoad(FALSE);
- seg = MAGet1Resource(kCode, segNum);
- SetResLoad(TRUE);
- GetResInfo(seg, id, kind, segName);
- //###SRF ProgramBreak("In " + s + form(" couldn''t load segment: %d", segNum) + segName);
- #endif
-
- Failure(memFullErr, 0);
- }
- }
- else
- (*gIsResidentSeg)[segNum - 1] = FALSE;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal void SetStackSpace(long numBytes)
- {
- long newLimit;
-
- newLimit = (long)GetCurStackBase() - numBytes;
- if ((long)GetApplLimit() > newLimit)
- SetApplLimit((Ptr)newLimit);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- class CTotalTempSize
- {
- Boolean &fJustLocked;
- Handle &fCanPurge;
- Size &fTotal;
- THz &fApplZone;
- public:
- CTotalTempSize(Boolean &justLocked,
- Handle &canPurge,
- Size &total,
- THz &applZone)
- :
- fJustLocked(justLocked),
- fCanPurge(canPurge),
- fTotal(total),
- fApplZone(applZone)
- {
- }
-
- pascal void TotalUp(Handle h);
- };
-
- #pragma segment MAMemoryRes
-
- pascal void CTotalTempSize::TotalUp(Handle h)
- {
- Boolean hIsLocked;
-
- if (!IsHandlePurged(h)) // in memory already
- if (HandleZone(h) == fApplZone) // in application heap
- {
- HNoPurge(h);
-
- hIsLocked = IsHandleLocked(h);
-
- if (!fJustLocked || hIsLocked)
- fTotal += GetHandleSize(h) + 8;
- // add in the size plus heap overhead
-
- if (!hIsLocked)
- if (fCanPurge == NULL)
- if (IsHandleEligible(h))
- fCanPurge = h;
- }
- }
-
- #pragma segment MAMemoryRes
-
- pascal Size TotalTempSize(Boolean justLocked,
- Handle &canPurge)
- {
- Size total;
- THz applZone;
- CTotalTempSize scopeLink(justLocked, canPurge, total, applZone);
-
- canPurge = NULL;
- total = 0;
- applZone = ApplicZone();
-
- ScanHandles((DoToHandlesType) & CTotalTempSize::TotalUp, &scopeLink);
-
- return total;
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- pascal void WithCodeResFileDo(DoWithResFileType DoWithResFile,
- void *scopeLink)
- {
- short oldResFile = MAUseResFile(gCodeRefNum);
-
- DoWithResFile(scopeLink);
-
- MAUseResFile(oldResFile);
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #pragma Push
- #if qTrace
- #pragma D+
- #endif
-
- /* no %_BP/%_EP allowed in here, because we
- cannot call to any other segment from this
- procedure */
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- class CUnloadAllSegments
- {
- long &jmpTablePtr;
- public:
- CUnloadAllSegments(long &aJmpTablePtr)
- :
- jmpTablePtr(aJmpTablePtr)
- {}
-
- #if qDebug
- pascal void DoToFrame(long,
- long ppc,
- long,
- long);
- #endif
-
- pascal void UnloadEm();
- };
-
- #if qDebug
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal void CUnloadAllSegments::DoToFrame(long,
- long ppc,
- long,
- long)
- {
- short itsSeg = GetSegFromPC(ppc);
- if ((itsSeg != 0) &&!(*gIsResidentSeg)[itsSeg - 1] && (*gIsLoadedSeg)[itsSeg - 1])
- {
- fprintf(stderr, "Segment#: %d", itsSeg);
- ProgramBreak("I really don''t think that you want to unload a segment into which you are going to return!");
- }
- }
- #endif
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- struct ModelFarCodeHeader
- {
- short field1;
- short field2;
- long A5OffsetOf16BitEntries;
- long numOf16BitEntries;
- long A5OffsetOf32BitEntries;
- long numOf32BitEntries;
- char otherEvenMorePrivateStuff; // You didn't think I would reveal any more than I had to…
- // did you?
- };
-
- typedef ModelFarCodeHeader *ModelFarCodeHeaderPtr,
- **ModelFarCodeHeaderHandle;
- const short kJTSkipOver = 2; /* size of jmp (or loadseg) instruction that
- must be skipped in the JT Entry in order
- to get to the target address */
-
- pascal void CUnloadAllSegments::UnloadEm()
- {
- short i;
- Handle seg;
-
- for (i = 0; i < pMaxSegNum; ++i)
- {
- if (!(*gIsResidentSeg)[i] && (*gIsLoadedSeg)[i])
- {
- seg = (*gCodeSegs)[i];
- if ((seg) &&!IsHandlePurged(seg))
- {
- // see the 32 B-E ERS (if you can find it)
- if (qModelFarCode)
- if ((*((ModelFarCodeHeaderHandle)seg))->numOf16BitEntries)
- UnLoadSeg((Ptr)(jumpTablePtr + (*((ModelFarCodeHeaderHandle) seg))->
- A5OffsetOf16BitEntries + kJTSkipOver));
- else // Has to be the other since we wouldn't even
- // have a segment otherwise
- UnLoadSeg((Ptr)(jumpTablePtr + (*((ModelFarCodeHeaderHandle)seg))->
- A5OffsetOf32BitEntries + kJTSkipOver));
- else
- UnloadSeg((Ptr)(jmpTablePtr + **((IntegerHandle)seg) + kJTSkipOver));
- (*gIsLoadedSeg)[i] = FALSE;
- }
- }
- }
- }
-
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal void UnloadAllSegments(void)
- {
- #if qDebug
- CheckRsrcUsage();
- #endif
-
- if (gUnloadAllSegs)
- {
- long jmpTablePtr = (long) (GetA5() + GetCurJTOffset());
- CUnloadAllSegments localScope(jmpTablePtr);
- #if qDebug
- EachFrameDo((long)GetCurStackFramePtr(), (long)(GetCurStackFramePtr() + 4), (DoToFrameType) & CUnloadAllSegments::
- DoToFrame, &localScope);
- #endif
-
- WithCodeResFileDo((DoWithResFileType) & CUnloadAllSegments::UnloadEm, &localScope);
-
- if (gSegReport)
- ProgramReport(" *** Just unloaded all segments ***", gMemMgtBreak);
- }
- }
- #pragma Pop
-
- //--------------------------------------------------------------------------------------------------
- #if qDebug
- #pragma segment MADebug
-
- pascal void WriteReserves()
- /* WRITELN's the temporary reserve and low-memory reserves in the
- debug window. */
-
- {
- WrLblPtr("Temporary reserve (pCodeReserve)", (long)pCodeReserve);
- fprintf(stderr, "\n");
- WrLblPtr("Low-memory reserve (pMemReserve)", (long)pMemReserve);
- fprintf(stderr, "\n");
- }
- #endif
-
-
-